#include "stdafx.h"
#include "PerspectiveViewVolume.h"
#include "glu.h"

//-------------------------------------------------------------------------
// constructors
//-------------------------------------------------------------------------

CPerspectiveViewVolume::CPerspectiveViewVolume()
{
	m_fAngleFOV = 60.0f;
	m_fNearZ = 0.1f;
	m_fFarZ = 1000.0f;
}

//-------------------------------------------------------------------------
// functions
//-------------------------------------------------------------------------

void CPerspectiveViewVolume::OnWindowResize()
{
	// Redefine the viewport to prevent distortion of image

	glViewport(m_nWndOriginX, m_nWndOriginY, m_nWndWidth, m_nWndHeight);

	// Set projection matrix to perspective for 3D

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	m_fAspect = (float)m_nWndWidth / (float)m_nWndHeight;
	gluPerspective(m_fAngleFOV, m_fAspect, m_fNearZ, m_fFarZ);		

	// Set matrix mode to model for screen geometry

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

}

//-------------------------------------------------------------------------

void CPerspectiveViewVolume::ExtractFrustumPlanes()
{
	matrix44f modelview, projection, clip;

	glGetFloatv(GL_PROJECTION_MATRIX, projection.m);
	glGetFloatv(GL_MODELVIEW_MATRIX, modelview.m);

	clip = projection * modelview;

	// right
	m_plnFrustum[0].Set(clip.m[3]-clip.m[0], clip.m[7]-clip.m[4], clip.m[11]-clip.m[8],  clip.m[15]-clip.m[12]);
	m_plnFrustum[0].Normalize();

	// left
	m_plnFrustum[1].Set(clip.m[3]+clip.m[0], clip.m[7]+clip.m[4], clip.m[11]+clip.m[8],  clip.m[15]+clip.m[12]);
	m_plnFrustum[1].Normalize();

	// bottom
	m_plnFrustum[2].Set(clip.m[3]+clip.m[1], clip.m[7]+clip.m[5], clip.m[11]+clip.m[9],  clip.m[15]+clip.m[13]);
	m_plnFrustum[2].Normalize();

	// top
	m_plnFrustum[3].Set(clip.m[3]-clip.m[1], clip.m[7]-clip.m[5], clip.m[11]-clip.m[9],  clip.m[15]-clip.m[13]);
	m_plnFrustum[3].Normalize();

	// far
	m_plnFrustum[4].Set(clip.m[3]-clip.m[2], clip.m[7]-clip.m[6], clip.m[11]-clip.m[10], clip.m[15]-clip.m[14]);
	m_plnFrustum[4].Normalize();

	// near
	m_plnFrustum[5].Set(clip.m[3]+clip.m[2], clip.m[7]+clip.m[6], clip.m[11]+clip.m[10], clip.m[15]+clip.m[14]);
	m_plnFrustum[5].Normalize();

}

//-------------------------------------------------------------------------

bool CPerspectiveViewVolume::SphereInFrustum(vector3f p, float radius)
{
	for (int i=0; i<6; i++)
	{
		if (m_plnFrustum[i].PointToPlaneDistance(p) <= -radius) return false;
	}
	
	return true;
}